package com.stateflow.engine.user.biz.impl;

import com.stateflow.engine.core.cache.UserAllDataCache;
import com.stateflow.engine.util.SignCheckUtils;
import com.stateflow.facade.common.cache.redis.RedisCache;
import com.stateflow.facade.common.exception.CommonException;
import com.stateflow.facade.common.model.req.CommonRequest;
import com.stateflow.facade.common.model.res.CommonResult;
import com.stateflow.facade.common.template.CommonTemplate;
import com.stateflow.facade.common.util.*;
import com.stateflow.facade.common.cache.redis.redisaffairs.RedisAffairs;
import com.stateflow.facade.common.cache.redis.redisaffairs.RedisAffairsModel;
import com.stateflow.facade.common.cache.redis.redisaffairs.RedisAffairsOperatorEnum;
import com.stateflow.facade.common.cache.redis.redisaffairs.RedisAffairsResult;
import com.stateflow.engine.config.RedisCacheKey;
import com.stateflow.engine.config.RedisConfig;
import com.stateflow.engine.user.biz.dto.cache.AccountUserCacheDTO;
import com.stateflow.engine.user.biz.dto.cache.UserAllDataCacheDTO;
import com.stateflow.engine.user.biz.dto.req.CreateUserReqDTO;
import com.stateflow.engine.user.biz.dto.req.LoginReqDTO;
import com.stateflow.engine.user.biz.service.UserInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by weiqingming on 2019/11/28.
 * 用户信息服务
 */
@Service
public class UserInfoServiceImpl implements UserInfoService,ApplicationRunner {

    private static final Logger LOGGER = LoggerFactory.getLogger(UserInfoServiceImpl.class);

    /** 缓存工具对象 */
    private RedisCache redisCache;

    @Override
    public CommonResult createUser(CommonRequest request) {
        return CommonTemplate.execute(request, LOGGER, new CommonTemplate() {
            @Override
            protected void check() {
                CreateUserReqDTO req = commonCheck(request, CreateUserReqDTO.class);
                //TODO 暂时不做账号格式校验
                CommonAssert.isNoBlankStr(req.getAccount(), "账号不能为空");
                CommonAssert.isNoBlankStr(req.getPassWord(), "密码不能为空");
                CommonAssert.isNoBlankStr(req.getSign(),"sign必传");
                SignCheckUtils.checkInteriorSign(req, req.getAccount(), req.getPassWord());
            }

            @Override
            protected CommonResult business() {
                CreateUserReqDTO req = getParam();

                //先查是否存在
                String AccountUserDataKey = RedisCacheKey.ACCOUNT_LINK_DATA(req.getAccount());
                AccountUserCacheDTO accountUser = redisCache.getCache(AccountUserDataKey);
                CommonAssert.isTrue(accountUser == null, "账号已经注册");


                //生成accessKey和accessSecret
                String accessKey = SeriaNumber.getNumber();
                String accessSecret = CommonUtils.md5(accessKey + System.currentTimeMillis());

                //创建accessKey做为主键缓存数据模型
                String userAllDataKey = RedisCacheKey.ACK_LINK_DATA(accessKey);
                String md5PassWord = CommonUtils.md5(req.getPassWord());
                UserAllDataCacheDTO data = new UserAllDataCacheDTO();
                data.setAccount(req.getAccount());
                data.setPassWord(md5PassWord);
                data.setAccessKey(accessKey);
                data.setAccessSecret(accessSecret);


                //创建account做为主键缓存数据模型
                accountUser = new AccountUserCacheDTO();
                accountUser.setAccount(req.getAccount());
                accountUser.setPassWord(md5PassWord);
                accountUser.setAccessKey(accessKey);


                //通过事物进行提交
                List<RedisAffairsModel> affairs = new ArrayList<>();
                affairs.add(new RedisAffairsModel(userAllDataKey, data, RedisAffairsOperatorEnum.INSERT));
                affairs.add(new RedisAffairsModel(AccountUserDataKey, accountUser, RedisAffairsOperatorEnum.INSERT));
                RedisAffairsResult affairsResult = RedisAffairs.affairs(redisCache, affairs);
                if (!affairsResult.isSuccess()) {
                    affairsResult.setTraceId(request.getTraceId());
                    LOGGER.error(affairsResult.getErrorMsg(), affairsResult);
                    throw new CommonException("创建用户信息失败，请重试");
                }

                return new CommonResult(data);
            }
        });
    }


    @Override
    public CommonResult login(CommonRequest request) {
        return CommonTemplate.execute(request, LOGGER, new CommonTemplate() {
            @Override
            protected void check() {
                LoginReqDTO req = commonCheck(request, LoginReqDTO.class);
                CommonAssert.isNoBlankStr(req.getAccount(), "账号不能为空");
                CommonAssert.isNoBlankStr(req.getPassWord(), "密码不能为空");
                CommonAssert.isNoBlankStr(req.getSign(),"sign必传");
                SignCheckUtils.checkInteriorSign(req, req.getAccount(), req.getPassWord());
            }

            @Override
            protected CommonResult business() {
                LoginReqDTO req = getParam();

                //先查是否存在
                String accountUserDataKey = RedisCacheKey.ACCOUNT_LINK_DATA(req.getAccount());
                AccountUserCacheDTO accountUser = redisCache.getCache(accountUserDataKey);
                CommonAssert.isNoRegister(accountUser != null);
                CommonAssert.isTrue(StringUtils.equals(accountUser.getPassWord(), req.getPassWord()), "账号或密码不正确");

                //取用户信息
                UserAllDataCacheDTO data = UserAllDataCache.get(accountUser.getAccessKey());
                CommonAssert.isNoEmptyObj(data,"获取用户信息失败，请重试");

                //仅返回用户基础信息，不返回状态流转配置信息
                data.setStateFlowConfigs(null);
                return new CommonResult(data);
            }
        });
    }

    @Override
    public void run(ApplicationArguments applicationArguments) throws Exception {
        redisCache = RedisConfig.REDIS_CACHE;
    }
}
